
local gdip = require "bindings.win32.gdiplus"
local win32 = require "bindings.win32"
local config = require "config"
local imageio = require "imageio"
local alien = require "alien"
local screen = require "guac.screen"
local print, setmetatable, error, type, tonumber
    = print, setmetatable, error, type, tonumber


module (...)


local dpi = tonumber(config.text_dpi) or 72

local boxed_ptr = alien.buffer(alien.sizeof('pointer'))
local boxed_float = alien.buffer(alien.sizeof('float'))

local fonts
if (gdip.NewPrivateFontCollection(boxed_ptr) ~= gdip.Ok) then
  error("[gdi+] unable to create private font collection")
end
fonts = boxed_ptr:get(1, "pointer")

local font_proto = {}
local font_meta = {__index = font_proto}

function loadfont(path, sz)
  if (gdip.PrivateAddFontFile(fonts, win32.MAKE_WIDE(path)) ~= gdip.Ok) then
    error("[gdi+] unable to load font")
  end
  local status, num = gdip.GetFontCollectionFamilyCount(fonts, 0)
  if (status ~= gdip.Ok) then
    error("[gdi+] unable to get number of fonts")
  end
  print("number of fonts: " .. num)
  local arr = alien.array("pointer", num)
  print("getlist:", gdip.GetFontCollectionFamilyList(fonts, num, arr.buffer, 0))
  local family = arr[num]
  print("createfont:", gdip.CreateFont(family, sz, gdip.FontStyleRegular, gdip.UnitPoint, boxed_ptr))
  font = boxed_ptr:get(1, "pointer")
  
  return setmetatable({font = font}, font_meta)
end

local ref_pixmap = imageio.createpixmap(256, 256, 4 * 256, 'r8g8b8a8', nil)

local ref_bitmap
print("createbitmap", gdip.CreateBitmapFromScan0(
  ref_pixmap.width, ref_pixmap.height, ref_pixmap.pitch, gdip.PixelFormat32bppARGB, ref_pixmap.buffer, boxed_ptr))
ref_bitmap = boxed_ptr:get(1, "pointer")

gdip.BitmapSetResolution(ref_bitmap, dpi, dpi)
gdip.GetImageHorizontalResolution(ref_bitmap, boxed_float)
print("hres", boxed_float:get(1, 'float'))
gdip.GetImageVerticalResolution(ref_bitmap, boxed_float)
print("vres", boxed_float:get(1, 'float'))

local strformat
gdip.StringFormatGetGenericTypographic(boxed_ptr)
strformat = boxed_ptr:get(1, "pointer")

local white_brush
print("CreateSolidFill", gdip.CreateSolidFill(0xffffffff, boxed_ptr))
white_brush = boxed_ptr:get(1, "pointer")

local layoutrect = gdip.RectF:new()

function font_proto:render(str)
  local ref_graphics
  print("GetImageGraphicsContext: ", gdip.GetImageGraphicsContext(ref_bitmap, boxed_ptr))
  ref_graphics = boxed_ptr:get(1, "pointer")
  
  gdip.SetTextRenderingHint(ref_graphics, gdip.TextRenderingHintAntiAliasGridFit)
  
  local wide = win32.MAKE_WIDE(str)
  local font = self.font
  
  local boundingBox = gdip.RectF:new()
  boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height = 0, 0, ref_pixmap.width, ref_pixmap.height
  print(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height)

  print("measurestring", gdip.MeasureString(ref_graphics, wide, #str, font, layoutrect(), strformat, boundingBox(), 0, 0))
  
  print(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height)

  print("clear", gdip.GraphicsClear(ref_graphics, 0x00000000))
  layoutrect.x, layoutrect.y, layoutrect.width, layoutrect.height = 0, 0, ref_pixmap.width, ref_pixmap.height
  print("drawstring", gdip.DrawString(ref_graphics, wide, #str, font, layoutrect(), strformat, white_brush))
  
  gdip.DeleteGraphics(ref_graphics)
  
  return screen.loadImage(ref_pixmap)
end

